package com.lie.prepare.multi_thread.specialLock;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

import static com.lie.prepare.util.Print.*;

/**
 * Created by lie on 2018/4/10.
 * 测试semaphore
 * 不过这个仅仅是个demo，并不是好的实践
 * 因为依赖于客户端使用完会check in
 */

class CheckoutTask<T> implements Runnable{

    private static int counter = 0;
    private final int id = counter++;

    private MyPool<T> pool;

    public CheckoutTask(MyPool<T> pool) {
        this.pool = pool;
    }

    public void run() {
        try {
            T item = pool.checkOut();
            print(this + "checkout = "+ item);
            //模拟持有了一段时间，然后check in
            TimeUnit.SECONDS.sleep(1);

            print(this + "checkIn = "+ item);
            pool.checkIn(item);

        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    public String toString() {
        return "CheckoutTask{" +
                "id=" + id +
                '}';
    }
}


public class SemaphoreDemo {
    final static int SIZE = 25;

    public static void main(String[] args) throws InterruptedException {
        final MyPool<Fat> pool = new MyPool<Fat>(Fat.class, SIZE);
        ExecutorService exec = Executors.newCachedThreadPool();
        for (int i = 0; i < SIZE; i++) {
            exec.execute(new CheckoutTask<Fat>(pool));
        }

        print("all checkout task created\n\n");
        List<Fat> fatList = new ArrayList<Fat>();
        for (int i = 0; i < SIZE; i++) {
            Fat f = pool.checkOut();
            print(i + ": main() checkout");
            f.operation();
            fatList.add(f);
        }

        //callable
        Future<?> blocked = exec.submit(new Runnable() {
            public void run() {
                try {
                    pool.checkOut();
                } catch (InterruptedException e) {
                    print("callable checkout interrupt");
                }
            }
        });

        TimeUnit.SECONDS.sleep(2);
        blocked.cancel(true);
        print("checking in objects in " + fatList+"\n\n");

        for (Fat f: fatList){
            pool.checkIn(f);
        }

        for (Fat f:fatList){
            pool.checkIn(f);//第二次check in会被忽略
        }

        exec.shutdown();

    }
}
